package com.lyl.label.common.config;

import com.lyl.label.common.exception.LabelException;
import com.lyl.label.common.result.Result;
import com.lyl.label.common.result.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.validation.ConstraintViolationException;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author Mr.Luo
 * @date 2022-06-21 14:45
 * @desc 全局异常处理
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
    /**
     * 处理自定义异常
     * @param e 自定义异常
     * @return Result
     */
    @ExceptionHandler(LabelException.class)
    public Result<String> onMyException(LabelException e){
        log.error("业务异常",e);
        return Result.build(e.getResultCode(),e.getErrorMsg());
    }

    /**
     * 校验请求参数(请求参数封装成实体类中)
     * @param e 校验请求参数
     * @return Result
     */
    @ExceptionHandler(BindException.class)
    public Result<Map<String, String>> onBindException(BindException e) {
        BindingResult bindingResult = e.getBindingResult();
        Map<String, String> errorMap = new HashMap<>();
        bindingResult.getFieldErrors().forEach((fieldError) ->
                errorMap.put(fieldError.getField(), fieldError.getDefaultMessage())
        );
        return Result.build(ResultCode.ILLEGAL_PARAM,errorMap);
    }

    /**
     * 校验请求参数
     * @param e 异常
     * @return result
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result<Map<String, String>> onMethodArgumentNotValidException(MethodArgumentNotValidException e){
        BindingResult bindingResult = e.getBindingResult();
        Map<String, String> errorMap = new HashMap<>();
        bindingResult.getFieldErrors().forEach((fieldError) ->
                errorMap.put(fieldError.getField(), fieldError.getDefaultMessage())
        );
        return Result.build(ResultCode.ILLEGAL_PARAM,errorMap);
    }

    /**
     * 校验请求参数(请求参数在方法形参列表中)
     * @param e 参数校验异常
     * @return Result
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public Result<Map<String, String>> onConstraintViolationException(ConstraintViolationException e){
        Map<String,String> errorMap = Stream.of(e.getMessage().split(",")).map(item -> item.split(":"))
                .collect(Collectors.toMap(item -> item[0].trim().substring(item[0].trim().indexOf(".") + 1), item ->
                        item[1].trim()
                ));
        return Result.build(ResultCode.ILLEGAL_PARAM,errorMap);
    }

    /**
     * 请求不存在
     * @param e 404异常
     * @return result
     */
    @ExceptionHandler(NoHandlerFoundException.class)
    public Result<Void> onNoHandlerFoundException(NoHandlerFoundException e){
        return Result.fail(ResultCode.URL_NOT_FOUND);
    }

    /**
     * 请求方式不支持
     * @param e 请求方式错误
     * @return result
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Result<Void> onHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e){
        return Result.fail(ResultCode.METHOD_NOT_SUPPORT);
    }


    /**
     * 系统异常
     * @param e 系统异常
     * @return Result
     */
    @ExceptionHandler(Exception.class)
    public Result<Object> onException(Exception e) {
        log.error("系统异常", e);
        return Result.build(ResultCode.UNKNOWN_EXCEPTION);
    }
}
